package com.tsite.common.report;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

abstract class ReportEngineAbstract {

	protected ReportEngineAbstract successor;	

	public void setSuccessor(ReportEngineAbstract successor) {
		this.successor = successor;
	}

	protected abstract <T> boolean handleReport(ReportRequest<T> reportRequest,
			ByteArrayOutputStream resultStream);
	
	protected final <T> JasperPrint fillingReportTemplate(ReportRequest<T> reportRequest) throws JRException{

		// 1. Retrieve template
		InputStream reportStream = this.getClass().getResourceAsStream(
				reportRequest.getReportTemplate());

		// 2. Convert template to JasperDesign
		JasperDesign jd = JRXmlLoader.load(reportStream);

		// 3. Compile design to JasperReport
		JasperReport jr = JasperCompileManager.compileReport(jd);

		// 4. Create the JasperPrint object
		// Make sure to pass the JasperReport, report parameters, and
		// data source
		JRDataSource datasource = new JRBeanCollectionDataSource(
				reportRequest.getDataSource());
		
		JasperPrint jp = JasperFillManager.fillReport(jr, reportRequest.getReportParms(),
				datasource);
		
		return jp;
	}

	public final <T> ByteArrayOutputStream export(ReportRequest<T> reportRequest)
			throws Exception {

		// Create an output byte stream where data will be written
		ByteArrayOutputStream resultStream = new ByteArrayOutputStream();

		boolean isHandled = this.handleReport(reportRequest, resultStream);
		if (!isHandled && successor == null) {
			throw new Exception("Requested report type does not support yet.");
		} else if (!isHandled && successor != null) {
			resultStream = successor.export(reportRequest);
		}
		
		return resultStream;
	}
}
